<?php

namespace Haozing\FastCore\Middleware;

use Haozing\FastCore\Context\UserContext;
use Haozing\FastCore\Exception\NoPermissionException;
use Hyperf\Context\Context;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Di\Annotation\Inject;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Qbhy\HyperfAuth\AuthManager;

class TenantMiddleware implements MiddlewareInterface
{

    #[Inject]
    protected AuthManager $auth;

    #[Inject]
    protected ConfigInterface $config;

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // 从配置文件中获取租户标识
        $tenantKey = $this->config->get('fastCore.tenant_key', 'tid');
        // 从路径中获取租户标识，路径为/xxx/tid/eee/ccc,其中tid和后面的eee为租户标识
        $tenantCode = '';
        if (str_contains($request->getUri()->getPath(), '/' . $tenantKey . '/')) {
            $path = explode('/', $request->getUri()->getPath());
            $tenantCode = $path[array_search($tenantKey, $path) + 1];
        }
        // 从Query中获取租户标识
        if (!empty($request->getQueryParams()[$tenantKey])) {
            $tenantCode = $request->getQueryParams()[$tenantKey] ?? '';
        }
        // 从Cookie中获取租户标识
        if (!empty($request->getCookieParams()[$tenantKey])) {
            $tenantCode = $request->getCookieParams()[$tenantKey] ?? '';
        }

        // 从请求头中获取租户标识
        if ($request->getHeaderLine($tenantKey)){
            $tenantCode = $request->getHeaderLine($tenantKey);
        }

        // 将请求头放到$request中
        if (!empty($tenantCode)) {
            //将租户id放入上下文中。
            Context::set('pp-tenant-code', $tenantCode);
            $request = Context::override(ServerRequestInterface::class, function (ServerRequestInterface $request) use ($tenantCode) {
                return $request->withAttribute('tid', $tenantCode);
            });
        }

        // 判断是否开启租户，并且用户登录
        if (!$this->auth->guard()->check()) {
            return $handler->handle($request);
        }

        $user = $this->auth->guard()->user();

        // 判断AuthUserContext上下文中是否存在
        if ($user && $user->toArray()) {
            $userInfo = $user->toArray();
            // 如果用户有tenantCode字段和$tenantCode不为空，并且不是超管，则判断是否一致
            if (isset($userInfo['tenant_code']) && !empty($tenantCode) && $userInfo['tenant_code'] != $tenantCode && isset($userInfo['is_super_admin']) && $userInfo['is_super_admin'] != 1) {
                throw new NoPermissionException('租户不一致');
            }
            UserContext::set($user->toArray());
        }

        return $handler->handle($request);
    }
}